package chu.dejian.widget.chartView;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.BarChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.SupportBarChart;
import org.achartengine.chart.XYChart;
import org.achartengine.model.SeriesSelection;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.renderer.support.SupportColorLevel;
import org.achartengine.renderer.support.SupportSeriesRender;
import org.achartengine.renderer.support.SupportTargetLineStyle;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import chu.dejian.entity.RecordEntity;
import com.sam.utils.display.DensityUtils;
import com.sam.utils.time.TimeUtils;

public abstract class BaseBPChartUtils {
    protected Context mContext;
    GraphicalView graphicalView = null;
    protected XYMultipleSeriesRenderer mXYMultiRenderer;
    protected XYMultipleSeriesDataset mXYMultipleSeriesDataSet;
    protected boolean showPoint = true;
    protected int lineColor = COLOR_MAIN_GRAY;
    protected int lineColor2 = COLOR_MAIN_GRAY2;
    protected SHOW_DAY_REACORD_WAY showDayReacordWay = SHOW_DAY_REACORD_WAY.LAST;

    private final static int COLOR_CHART_GRID = Color.parseColor("#55797C7E"); //图表网格和坐标颜色
    private final static int COLOR_CLICKED_BG = Color.parseColor("#5DBEF5"); //点击点之后上面浮动的气泡文字的气泡背景颜色
    private final static int COLOR_MAIN_GRAY = Color.parseColor("#929292"); //线条的灰色
    private final static int COLOR_MAIN_GRAY2 = Color.parseColor("#525252"); //线条的灰色
    private final static int COLOR_MAIN_BLUE = Color.parseColor("#5DBEF5"); //文字，提示背景等蓝色，这是主色调
    private final static int COLOR_ORANGE_LEVEL = Color.parseColor("#FFFF9432");
    private final static int COLOR_RED_LEVEL = Color.parseColor("#DDFA3D35");
    private final static int COLOR_GREEN_LEVEL = Color.parseColor("#DF1A9B32");

    private final static String CHART_TITLE_STR = "";
    private final static String X_TITLE = "";
    private final static String Y_TITLE = "";
    private final static String TARGET_DES_STR = "NORMAL";

    private final static int Y_LABEL_SCALES = 6;
    private final static int X_LABEL_SCALES = 0;
    private final static int CLICK_POINT_AREA_SIZE = 20;
    private final static float TARGET_VALUE = 80f;
    private final static int X_AXIS_MAX_VALUE = 6;
    private final static int X_AXIS_MIN_VALUE = 0;
    private final static int Y_AXIS_MAX_VALUE = 200;
    private final static int Y_AXIS_MIN_VALUE = 0;
    private final static int AXIS_TITLE_TEXT_SIZE = 0;
    private final static int CHART_TITLE_TEXT_SIZE = 0;
    private static float POINT_SIZE = 12f;
    private static int FIRST_LABELS_TEXT_SIZE = 48;
    private static int SECOND_LABELS_TEXT_SIZE = 42;
    private static int LEGEND_TEXT_SIZE = 10;
    private static int MARGIN_TOP = 0;
    private static int MARGIN_LEFT = 30;
    private static int MARGIN_BOTTOM = 80;
    private static int MARGIN_RIGHT = 30;
    private static int Y_LABELS_PADDING = 50;
    private static int X_LABELS_PADDING = 30;
    private static float LINE_WIDTH = 7f;

    private void initParameters(Context context){
        POINT_SIZE = DensityUtils.dp2px(context,4);
        FIRST_LABELS_TEXT_SIZE = DensityUtils.sp2px(context,16);
        SECOND_LABELS_TEXT_SIZE = DensityUtils.sp2px(context,14);
        LEGEND_TEXT_SIZE = DensityUtils.sp2px(context,3);
        MARGIN_TOP = DensityUtils.dp2px(context,0);
        MARGIN_LEFT = DensityUtils.dp2px(context,10);
        MARGIN_BOTTOM = DensityUtils.dp2px(context,27);
        MARGIN_RIGHT = DensityUtils.dp2px(context,10);
        Y_LABELS_PADDING = DensityUtils.dp2px(context,17);
        X_LABELS_PADDING = DensityUtils.dp2px(context,10);
        LINE_WIDTH = DensityUtils.dp2px(context,2.5f);
    }

    public enum CHART_STYLE {
        LINE(0),CUBE_LINE(1),BAR(2),SCATTER(3),TIME(4),SUPPORT_BAR(5),SUPPORT_LINE(6),SUPPORT_CUBE(7);
        int value = 0;
        CHART_STYLE(int value){
            this.value = value;
        }
        public static CHART_STYLE fromInt(int value){
            switch (value){
                case 0: return LINE;
                case 1: return CUBE_LINE;
                case 2: return BAR;
                case 3: return SCATTER;
                case 4: return TIME;
                case 5: return SUPPORT_BAR;
                case 6: return SUPPORT_LINE;
                case 7: return SUPPORT_CUBE;
                default:return null;
            }
        }
        public int value(){
            return value;
        }
    }

    public enum SHOW_DAY_REACORD_WAY { // 如果每天测量了多次，则在图标中显示的点为每天的哪条记录，第一条，最后一条，所有记录平均值
        FIRST(0),LAST(1);//,AVERAGE(2);
        private int value;
        SHOW_DAY_REACORD_WAY(int value) {
            this.value = value;
        }
        public static SHOW_DAY_REACORD_WAY fromInt(int value){
            switch (value){
                case 0: return FIRST;
                case 1: return LAST;
//                case 2: return AVERAGE;
                default:return LAST;
            }
        }
    }

    public SHOW_DAY_REACORD_WAY getShowDayReacordWay() {
        return showDayReacordWay;
    }

    public void setShowDayReacordWay(SHOW_DAY_REACORD_WAY showDayReacordWay) {
        this.showDayReacordWay = showDayReacordWay;
    }

    public BaseBPChartUtils(Context context) {
        this(context,COLOR_MAIN_GRAY,true);
    }

    public BaseBPChartUtils(Context context,int lineColor,boolean showPoint) {
        this.mContext = context;
        this.showPoint = showPoint;
        this.lineColor = lineColor;
        initParameters(context);
        mXYMultiRenderer = getChartRenderer();
        mXYMultipleSeriesDataSet = new XYMultipleSeriesDataset();
    }

    //--------------------------------------------------------------------------------------
    public abstract void setRecordEntityList(List<RecordEntity> recordEntityList);
    public abstract List<RecordEntity> getShownRecordList();
    public abstract List<List<RecordEntity>> getGroupedRecordLists();


    protected List<List<RecordEntity>> groupRecordByDay(List<RecordEntity> recordEntityList){
        if(recordEntityList == null || recordEntityList.size() == 0) return null;
        RecordEntity preRecord = recordEntityList.get(0);
        RecordEntity currRecord = null;
        List<RecordEntity> currRecordList = new ArrayList<>();
        List<List<RecordEntity>> recordLists = new ArrayList<>();
        recordLists.add(currRecordList);
        currRecordList.add(preRecord);

        for(int i = 1; i < recordEntityList.size(); i++){
            currRecord = recordEntityList.get(i);
            if(!TimeUtils.isTheSameDay(preRecord.getMeasureDateTime(),currRecord.getMeasureDateTime())){
                currRecordList = new ArrayList<>();
                recordLists.add(currRecordList);
            }
            currRecordList.add(currRecord);
            preRecord = currRecord;
        }
        return recordLists;
    }

    protected List<RecordEntity> getSameDayRecords(List<List<RecordEntity>> recordEntityLists,RecordEntity recordEntity){
        int size = recordEntityLists.size();
        if(recordEntityLists == null || recordEntityLists.size() == 0 || recordEntity == null) return null;
        for(int i = 0; i < size; i++){
            List<RecordEntity> recordEntityList = recordEntityLists.get(i);
            if(recordEntityList == null || recordEntityLists.size() == 0 || recordEntityList.get(0) == null) continue;
            if(TimeUtils.isTheSameDay(recordEntityList.get(0).getMeasureDateTime(),recordEntity.getMeasureDateTime())) return recordEntityLists.get(i);
        }
        return null;
    }

    public void addLine(XYSeries pointsDataSeries, XYSeriesRenderer lineRender, SupportSeriesRender colorLevelRender){
        mXYMultipleSeriesDataSet.addSeries(pointsDataSeries);
        mXYMultiRenderer.addSeriesRenderer(lineRender);
        mXYMultiRenderer.addSupportRenderer(colorLevelRender);
    }

    public void setXFirstLabels(String[] xFirstLabels){
        for(int i = 0; i < xFirstLabels.length; i++){
            mXYMultiRenderer.addXFirstTextLabel(i,xFirstLabels[i]);
        }
    }
    public void setXSecondLabels(String[] xSecondLabels){
        for(int i = 0; i < xSecondLabels.length; i++){
            mXYMultiRenderer.addXSecondTextLabel(i,xSecondLabels[i]);
        }
    }
    public void setXFirstLabels(Map<Double,String> xFirstLabelsMap){
        Iterator it = xFirstLabelsMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            mXYMultiRenderer.addXFirstTextLabel((Double) entry.getKey(), (String) entry.getValue());
        }
    }
    public void setXSecondLabels(Map<Double,String> xSecondLabels){
        Iterator it = xSecondLabels.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            mXYMultiRenderer.addXSecondTextLabel((Double) entry.getKey(), (String) entry.getValue());
        }
    }
    //--------------------------------------------------------------------------------------
    protected XYSeries getPointDataSeries(String title, double[] pointsValue){
        XYSeries defaultSeries = new XYSeries(title);
        if(pointsValue != null && pointsValue.length != 0){
            for (int i = 0; i < pointsValue.length; i++) {
                if(pointsValue[i] > 0) defaultSeries.add(i, pointsValue[i]);
            }
        }
        return defaultSeries;
    }

    public class ChartPoint{
        public int pointIndex;
        public double pointYValue;

        public ChartPoint(int pointIndex, double pointYValue) {
            this.pointIndex = pointIndex;
            this.pointYValue = pointYValue;
        }
    }

    protected SupportSeriesRender getSysLevelRender(){
        // 设置折线颜色属性
        final SupportSeriesRender sysLineSeriesRender = new SupportSeriesRender();
        // 若有多个颜色等级可以使用这个用法
        ArrayList<SupportColorLevel> sysColorLevelList = new ArrayList<SupportColorLevel>();
        sysColorLevelList.add(new SupportColorLevel(40, 90, COLOR_ORANGE_LEVEL));
        sysColorLevelList.add(new SupportColorLevel(90, 140, COLOR_GREEN_LEVEL));
        sysColorLevelList.add(new SupportColorLevel(140, 190, COLOR_RED_LEVEL));

        sysLineSeriesRender.setClickPointColor(COLOR_CLICKED_BG);
        sysLineSeriesRender.setColorLevelValid(true);
        sysLineSeriesRender.setColorLevelList(sysColorLevelList);
//        sysLineSeriesRender.setShapeLineColor(new int[]{COLOR_GREEN_LEVEL,COLOR_ORANGE_LEVEL,COLOR_RED_LEVEL});
        return sysLineSeriesRender;
    }

    protected SupportSeriesRender getDiaLevelRender(){
        final SupportSeriesRender diaLineSeriesRender = new SupportSeriesRender();
        // 若有多个颜色等级可以使用这个用法
        ArrayList<SupportColorLevel> diaColorLevelList = new ArrayList<SupportColorLevel>();
        diaColorLevelList.add(new SupportColorLevel(30, 60, COLOR_ORANGE_LEVEL));
        diaColorLevelList.add(new SupportColorLevel(60, 90, COLOR_GREEN_LEVEL));
        diaColorLevelList.add(new SupportColorLevel(90, 120, COLOR_RED_LEVEL));

        diaLineSeriesRender.setClickPointColor(COLOR_CLICKED_BG);
        diaLineSeriesRender.setColorLevelValid(true);
        diaLineSeriesRender.setColorLevelList(diaColorLevelList);
//        diaLineSeriesRender.setShapeLineColor(new int[]{COLOR_GREEN_LEVEL,COLOR_ORANGE_LEVEL,COLOR_RED_LEVEL});
        return diaLineSeriesRender;
    }

    protected XYSeriesRenderer getLineSeriesRender(int lineColor){
        XYSeriesRenderer renderer = new XYSeriesRenderer();
        renderer.setColor(lineColor);
        renderer.setDisplayChartValues(false);  // 设置是否在点上显示数据
        renderer.setLineWidth(LINE_WIDTH);    //设置曲线的宽度
        renderer.setFillPoints(true);   //是否是实心的点
        renderer.setPointStyle(PointStyle.CIRCLE);
        return renderer;
    }

    protected XYMultipleSeriesRenderer getChartRenderer() {
        XYMultipleSeriesRenderer mXYMultiRenderer = new XYMultipleSeriesRenderer();
        mXYMultiRenderer.setChartTitle(CHART_TITLE_STR);
        mXYMultiRenderer.setXTitle(X_TITLE);
        mXYMultiRenderer.setYTitle(Y_TITLE);
        mXYMultiRenderer.setBackgroundColor(Color.WHITE);// 设置背景颜色
        mXYMultiRenderer.setMarginsColor(Color.WHITE);// 设置页边空白的颜色
        mXYMultiRenderer.setApplyBackgroundColor(false);// 设置背景颜色生效
        mXYMultiRenderer.setXAxisMax(X_AXIS_MAX_VALUE);
        mXYMultiRenderer.setXAxisMin(X_AXIS_MIN_VALUE );
        mXYMultiRenderer.setYAxisMax(Y_AXIS_MAX_VALUE);
        mXYMultiRenderer.setYAxisMin(Y_AXIS_MIN_VALUE);
        mXYMultiRenderer.setPointSize(showPoint ? POINT_SIZE : 0);
        mXYMultiRenderer.setXFirstLabelsColor(COLOR_MAIN_GRAY);// 设置坐标轴,轴标签的颜色
        mXYMultiRenderer.setXSecondLabelsColor(COLOR_MAIN_GRAY);// 设置坐标轴,轴标签的颜色
        mXYMultiRenderer.setXSelectedFirstLabelsColor(COLOR_MAIN_BLUE);// 设置坐标轴,轴标签的颜色
        mXYMultiRenderer.setXSelectedSecondLabelsColor(COLOR_MAIN_BLUE);// 设置坐标轴,轴标签的颜色
        mXYMultiRenderer.setYLabelsColor(0, COLOR_MAIN_BLUE);// 设置坐标轴,轴的颜色
        mXYMultiRenderer.setGridColor(COLOR_CHART_GRID);//设置网格的颜色
        mXYMultiRenderer.setYLabels(Y_LABEL_SCALES );// 设置Y轴显示的刻度数
        mXYMultiRenderer.setXLabels(X_LABEL_SCALES ); // 设置 X 轴不显示数字（改用我们手动添加的文字标签）
        mXYMultiRenderer.setXLabelsAlign(Paint.Align.CENTER);// 设置x,y轴显示的排列,默认是 Align.CENTER
        mXYMultiRenderer.setYLabelsAlign(Paint.Align.RIGHT);
        mXYMultiRenderer.setAntialiasing(true);  // 开启平滑
        mXYMultiRenderer.setFitLegend(true);  // 调整合适的位置
        mXYMultiRenderer.setShowAxes(false);  // 设置坐标轴是否可见
        mXYMultiRenderer.setShowLegend(false);  // 设置是否显示图例.
        mXYMultiRenderer.setZoomEnabled(false, false);// 是否支持图表移动
        mXYMultiRenderer.setSelectableBuffer(CLICK_POINT_AREA_SIZE);// 点击区域大小
        mXYMultiRenderer.setTargetLineVisible(true); //设置目标线
        mXYMultiRenderer.setTargetLineColor(COLOR_CHART_GRID);
        mXYMultiRenderer.setTargetValue(TARGET_VALUE);
        mXYMultiRenderer.setTargetValue(100);
        mXYMultiRenderer.setTargetLineStyle(SupportTargetLineStyle.Line_Dotted);
        mXYMultiRenderer.setTargetDescription(TARGET_DES_STR);
        mXYMultiRenderer.setAxisTitleTextSize(AXIS_TITLE_TEXT_SIZE ); // 坐标轴标题字体大小：
        mXYMultiRenderer.setChartTitleTextSize(CHART_TITLE_TEXT_SIZE); // 图表标题字体大小：
        mXYMultiRenderer.setFirstLabelsTextSize(FIRST_LABELS_TEXT_SIZE); // X轴一级标签字体大小：
        mXYMultiRenderer.setSecondLabelsTextSize(SECOND_LABELS_TEXT_SIZE); // X二级轴标签字体大小：
        mXYMultiRenderer.setLegendTextSize(LEGEND_TEXT_SIZE ); // 图例字体大小,即左下角标注颜色对应意义的文字字体： 15
        mXYMultiRenderer.setMargins(new int[]{MARGIN_TOP, MARGIN_LEFT, MARGIN_BOTTOM, MARGIN_RIGHT});
        mXYMultiRenderer.clearYTextLabels();
        mXYMultiRenderer.setPanEnabled(true,false); // 是否可以移动
        mXYMultiRenderer.setShowCustomTextGridY(false);
        mXYMultiRenderer.setYLabelsPadding(Y_LABELS_PADDING);
        mXYMultiRenderer.setXLabelsPadding(X_LABELS_PADDING);
        mXYMultiRenderer.setClickEnabled(true);//是否可点击
        mXYMultiRenderer.setShowGridX(true);
        mXYMultiRenderer.setShowGrid(false);//设置网格是否显示

//        Typeface typeFace = Typeface.createFromAsset(mContext.getAssets(), "fonts/Futura.ttc");
//        mXYMultiRenderer.setTextTypeface(typeFace);
        return mXYMultiRenderer;
    }
    //--------------------------------------------------------------------------------------
    public GraphicalView createChartView(CHART_STYLE chartStyle) {
        //获取线表View
        if(chartStyle == CHART_STYLE.LINE){
            graphicalView = ChartFactory.getLineChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer);
        } else if(chartStyle == CHART_STYLE.CUBE_LINE){
            graphicalView = ChartFactory.getSupportCubeLineChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer, 0.2f);
        } else if(chartStyle == CHART_STYLE.BAR){
            graphicalView = ChartFactory.getBarChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer, BarChart.Type.DEFAULT);
        } else if(chartStyle == CHART_STYLE.SCATTER){
            graphicalView = ChartFactory.getScatterChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer);
        } else if(chartStyle == CHART_STYLE.TIME){
            graphicalView = ChartFactory.getTimeChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer,"yyyy-MM-dd HH:mm:ss");
        } else if(chartStyle == CHART_STYLE.SUPPORT_BAR){
            graphicalView = ChartFactory.getSupportBarChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer, SupportBarChart.Type.DEFAULT);
        } else if(chartStyle == CHART_STYLE.SUPPORT_LINE){
            graphicalView = ChartFactory.getSupportLineChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer);
        } else if(chartStyle == CHART_STYLE.SUPPORT_CUBE){
            graphicalView = ChartFactory.getSupportCubeLineChartView(mContext, mXYMultipleSeriesDataSet, mXYMultiRenderer,0.2f);
        }
        //获取线表View点击的点
        graphicalView.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                GraphicalView gv = (GraphicalView) v;
                //将view转换为可以监听的GraphicalView
                SeriesSelection ss = gv.getCurrentSeriesAndPoint();
                //获得被点击的系列和点
                if (ss == null || onPointClickListener == null) return ;
                //获得当前被点击点的X位置和Y数值
                onPointClickListener.onPointClicked(ss.getXValue(), ss.getValue());
            }
        });
        return graphicalView;
    }

    public void setOnChartItemClickListener(XYChart.ChartItemClickListener chartItemClickListener){
        graphicalView.setOnChartItemClickListener(chartItemClickListener);
    }

    OnPointClickListener onPointClickListener;
    public void setOnPointClickedListener(OnPointClickListener onPointClickListener){
        this.onPointClickListener = onPointClickListener;
    }

    public interface OnPointClickListener{
        void onPointClicked(double pointX, double pointY);
    }

}
